經過一整天的奮鬥終於做出還算能用的發票掃描器了TAT (如果有更好的方法請告訴我,拜託!
我們採用最簡單暴力的方法,以畫面中心線分左右,先紀錄有統ㄧ編號的左側 QRcode 在紀錄右側,相加後上傳DB
//參考
let RawTest = {
bounds: {
origin: { x: "165.187563", y: "166.461469" },
size: { width: "91.109270", height: "94.537594" },
__proto__: Object,
},
data: "VA12528817108100173340000018d000001a10000000082869675fWQkJz5mI0mJ3MNvZGbOmg==:**********:1:1:1:餐品:1:417:",
rawData: "46c56413132353238383137313038313030313733333430303030303138643030303030316131303030303030303038323836393637356657516b4a7a356d49306d4a334d4e765a47624f6d673d3d3a2a2a2a2a2a2a2a2a2a2a3a313a313a313ae9a490e593813a313a3431373a0ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11ec11",
target: 419,
type: "org.iso.QRCode",
}
以下是實作邏輯A
求出掃描範圍 h667*w375
w的一半約 188 =中心點(紅線)
> let cameraViewPrintrt = this.state.cameraView_XY.x * 0.5;
如果QRcode為 w100*h100,左上角的位置為x,右上為x+w100
> let x = e.bounds.origin.x;
> let width = e.bounds.size.width;
轉數字
> let num = x * 1 + width * 1;
判斷右上是否超過中線
> if (x+w100 < cameraViewPrintrt){///左側 QRcode}
我好想直接遮住鏡頭喔....(太廢
以下是實作邏輯B
////掃描到SN+第二張的**才關閉相機
if (data.startsWith('**')&&data.length>2) {
////我是第二張
}
if (!data.startsWith('**')
&&/[0-9]/.match(data[2-10])
&&(/[a-z]/.match(data[0&1])) {
////我是第一張
}
求出掃描範圍
this.state.cameraView_XY={w:375,h:667};
_onLayout(event){
//使用大括號是為了限制讓結構賦值得到的變量的作用域,因為接來下還要結構解構賦值一次
{
//獲取外層View的寬高,以及左上角的坐標值
令{x,y,width,height} = event.nativeEvent.layout;
this.setState({cameraView_XY:{“ w”:+ width,“ h”:+ height}})
// console.warn('通過onLayout得到的寬度:'+ width);
// console.warn('通過onLayout得到的高度:'+ height);
}
//通過維度API獲取View寬高
讓{width,height} = Dimensions.get('window');
// console.warn('通過Dimensions得到的寬度:'+ width);
// console.warn('通過Dimensions得到的高度:'+ height);
}
小提醒
記得使用上圖 React Native 自帶的 Remote Debugging 工具,或是 React Developer Tools ,忘記可以參考下圖
/* eslint-disable prettier/prettier */
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
Dimensions,
Alert,
} from 'react-native';
import QRCodeScanner from 'react-native-qrcode-scanner';
import Marker from './Marker/Marker';
let data = null;
const data_Context = React.createContext(data);
const DB = [
{ "num": "25576066", "txt": "1,000萬元" },
{ "num": "19614436", "txt": "20萬元" },
{ "num": "96182420", "txt": "頭獎20萬元" },
{ "num": "47464012", "txt": "頭獎20萬元" },
{ "num": "62781818", "txt": "頭獎20萬元" },
{ "num": "066", "txt": "頭獎20萬元" },
{ "num": "899", "txt": "頭獎20萬元" },
]
import firebase from 'react-native-firebase';
const iosConfig = {
// 你的設定
};
const itHelpApp = firebase.initializeApp(iosConfig);
// itHelpApp.onReady().then((app) => {
// firebase.app('kittens').auth().signInAnonymously().then((user) => {
// console.log('kittensApp user ->', user.toJSON());
// });
// });
export { data_Context }
export default class Scanner extends Component {
constructor(props) {
super(props);
this.state = {
userToken: "A",
camera: false,
A: false,
camera_state: true,
myName: null,
rawData_L: "",
rawData_R: "",
cameraView_XY: [],
AwaitNextBounds: true,
};
}
state = {
isValid: null,
}
updata(docID, data) {
// let docID = "HQ255760627"
const ref = firebase.firestore().collection('receipt').doc(docID);
let SN = this.cutString(data, 10, 2);
// 也可以获取当前的毫秒级时间戳
var time = Date.now();
var date = new Date(time * 1000);
var dt = date.getFullYear() + "-" + (date.getMonth() < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + "-" + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
itHelpApp.onReady().then((app) => {
app.firestore()
.runTransaction(async transaction => {
const doc = await transaction.get(ref);
if (!doc.exists) {
transaction.set(ref, { onCreate: dt, timer: time, serialNumber: SN, content: data });
return null;
}
})
.then(newPopulation => {
console.log(
`Transaction successfully committed and new population is '${newPopulation}'.`
);
})
.catch(error => {
console.log('Transaction failed: ', error);
});
});
}
componentDidMount() {
///生命週期 component 載入前執行
// this.updata();
this.setState({
AwaitNextBounds: true,
});
}
componentWillReceiveProps(nextProps) {
this.setState({
camera: nextProps.camera,
});
}
cutString(str, len, start, suffix) {
if (!str) return "";
if (len <= 0) return "";
if (!suffix) suffix = "";
var templen = 0;
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 255) {
templen += 2;
} else {
templen++
}
if (templen == len) {
return str.substring(start, i + 1) + suffix;
} else if (templen > len) {
return str.substring(start, i) + suffix;
}
}
return str;
}
Checkprize(str) {
for (i = 0; i < 7; i++) {
let ANS = str.lastIndexOf(DB[i].num);
if (ANS > 2) {
let txt = "WIN~~~"
return txt
}
else if (ANS == 0) {
let txt = "~~~WIN~~~"
return txt;
}
}
}
onSuccess = async (e) => {
data = e.data;
const dataWithoutSpaces = data.trim();
let x = e.bounds.origin.x;
let y = e.bounds.origin.y;
let width = e.bounds.size.width;
let cameraViewPrintrt = this.state.cameraView_XY.x * 0.5;
let num = x * 1 + width * 1;
console.log(num, cameraViewPrintrt, x, y, width, this.state.cameraView_XY);
console.log(this.state.AwaitNextBounds);
if (num < cameraViewPrintrt && this.state.AwaitNextBounds == true) {
console.log("A");
if (!data.startsWith('**')
&& !data.startsWith('http')
&& dataWithoutSpaces.length >= 77
) {
console.log("A以驗證");
this.setState({
AwaitNextBounds: false,
rawData_L: dataWithoutSpaces
}, () => {
console.log("A以存入");
});
}
}
else {
console.log("B");
if (data.startsWith('**')
&& !data.startsWith('http')
&& dataWithoutSpaces.length > 2
// && dayjs(dateText).isValid()
) {
console.log("B以驗證");
this.setState({
rawData_R: dataWithoutSpaces
}, () => {
if (this.state.rawData_L !== "") {
let data = this.state.rawData_L + this.state.rawData_R;
let docID = this.cutString(this.state.rawData_L, 10, 0);
console.log(data);
Alert.alert(data);
this.updata(docID, data);
} else {
console.log("B以驗證,A還沒來");
}
});
console.warn("OKOKOKOK");
}
}
}
_onLayout(event) {
let { x, y, width, height } = event.nativeEvent.layout;
this.setState({ cameraView_XY: { "x": +width, "y": +height } })
// console.warn('通过onLayout得到的宽度:' + width);
// console.warn('通过onLayout得到的高度:' + height);
}
render() {
const { closeScanner } = this.props
const { isValid } = this.state
const markerColor = (() => {
if (isValid === null) { return 'rgb(255, 204, 0)' }
return isValid ? 'rgb(76, 217, 100)' : 'rgb(255, 59, 48)'
})()
const CustomMarker = Marker(markerColor, closeScanner)
const cameraProps = { captureAudio: false }
return (
<View style={styles.container} onLayout={this._onLayout.bind(this)} >
<QRCodeScanner
onRead={this.onSuccess}
topContent={null}
// reactivate={this.state.camera_state}
reactivate={true}
cameraProps={cameraProps}
showMarker
fadeIn={false}
customMarker={CustomMarker}
cameraStyle={styles.camera}
//reactivate={false}
/////////切換頁面時要關閉/開啟
reactivateTimeout={1500}
bottomContent={
<TouchableOpacity style={styles.buttonTouchable} onPress={() => {
this.setState({ camera_state: !this.state.camera_state })
this.testForceFun.bind(this)
}} >
<Text style={styles.buttonText}>{this.state.camera_state}</Text>
</TouchableOpacity>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
camera: {
height: Dimensions.get('window').height,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
}, centerText: {
flex: 1,
fontSize: 18,
padding: 32,
color: '#777',
},
textBold: {
fontWeight: '500',
color: '#000',
},
buttonText: {
fontSize: 21,
color: 'rgb(0,122,255)',
},
buttonTouchable: {
padding: 16,
},
});